package lib

import (
	"GameServer/Common/utils"
	"GameServer/conf"
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/globalsign/mgo/bson"

	"GameServer/Common/data"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	"GameServer/Game/m"
	"GameServer/Game/plog"
	"GameServer/Game/sp"
)

var Upper []string = []string{
	"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
	"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
	"U", "V", "W", "X", "Y", "Z",
}

//
func NewRobot() (u *m.User, lockBlock *m.LockBlock, layer *m.Layer, err error) {
	lockBlockTid := utils.RandomInt64(1, 63)
	number := utils.RandomInt64(1, 1000)
	u = &m.User{
		Robot:         true,
		Uid:           bson.NewObjectId(),
		Number:        number,
		Name:          fmt.Sprintf("%s", utils.GenName()),                  //生成随机名字
		Head:          fmt.Sprintf("%s", utils.GenDefaultHead()),           //随机头像4选1
		Gold:          utils.RandomInt64(50000, 10000) * lockBlockTid * 10, // 机器人金币上调10倍
		Diamon:        utils.RandomInt64(1, 100000),
		Shield:        utils.RandomInt64(0, 3),
		LastLoginTime: utils.TNow().Unix(),
		Pos:           &m.PosInfo{LockBlockTid: lockBlockTid, LayerId: 1},
		MaxPos:        &m.PosInfo{LockBlockTid: lockBlockTid, LayerId: 1},
		AvatarFrame:   data.AvatarFrameEnum.DefaultFrame, // 默认头像框
	}
	lockBlock, layer, err = RobotGenerateLockBlock(u.Uid.Hex(), uint64(lockBlockTid), nil, true)
	if err != nil {
		return
	}
	RobotOpenSomeGrid(u, layer)
	return
}

// 新手引导机器人
func NewGuildRobot() (u *m.User, layer *m.Layer, err error) {
	u = &m.User{
		Robot:         true,
		Uid:           bson.NewObjectId(),
		Number:        utils.RandomInt64(1, 1000),
		Name:          "Simon",
		Head:          "piggy_head",
		Gold:          150000,
		Diamon:        utils.RandomInt64(1, 100000),
		Shield:        0, // 新手引导机器人不能有盾
		LastLoginTime: utils.TNow().Unix(),
		Pos:           &m.PosInfo{LockBlockTid: 1, LayerId: 1},
		MaxPos:        &m.PosInfo{LockBlockTid: 1, LayerId: 1},
		AvatarFrame:   data.AvatarFrameEnum.DefaultFrame, // 默认头像框
	}
	layer, err = RobotGenerateFireLockBlock()
	return
}

// 给机器人打开几个格子
func RobotOpenSomeGrid(u *m.User, layer *m.Layer) {
	num := 0
	for _, item := range layer.GridList {
		if num < 5 {
			num++
			continue
		}
		item.Status = 0
	}
}

//
func Register(name, head, accountId, faceBookId string, platform int64, langsTyp string, count int64) (u *m.User, err error) {
	u = new(m.User)
	if accountId != "" {
		err = u.FindByAccountId(accountId)
		if err != nil {
			if errors.ErrCode(err) != data.Errcode.UserNotFound {
				err = errors.NewErrcode(data.Errcode.UserNameExist, "accountId已经存在")
				return
			}
		}
	}

	name = CreateName(name, count)
	identifId := CreateIdentifId(count)

	uidObject := bson.NewObjectId()
	lockBlockInfo, err := GenerateLockBlockFirst(uidObject.Hex())
	if err != nil {
		return nil, err
	}
	nowUnix := utils.TNow().Unix()
	u = &m.User{
		Uid:             uidObject,
		AccountId:       accountId,
		FaceBookId:      faceBookId,
		IdentifId:       identifId,
		Number:          1 + count,
		Name:            name,
		Head:            head,
		Gold:            data.InitResourcesEnum.Gold,
		Diamon:          data.InitResourcesEnum.Diamon,
		Shield:          0,
		Energy:          data.InitResourcesEnum.Energy,
		SlotLv:          1,
		RegisterTime:    nowUnix,
		LastLoginTime:   nowUnix,
		Pos:             &m.PosInfo{LockBlockTid: 1, LayerId: 1},
		MaxPos:          &m.PosInfo{LockBlockTid: 1, LayerId: 1},
		Platform:        platform,
		UsedName:        name,
		AvatarFrame:     data.AvatarFrameEnum.DefaultFrame, // 当前使用头像框
		UserGroup:       0,                                 // 用户分组
		LangsTyp:        langsTyp,
		EnergyTime:      nowUnix,
		NextRecoverTime: 3600,
	}

	u.AddAvatarFrame(data.AvatarFrameEnum.DefaultFrame) // 内含数组实例化

	// 添加玩家记录所有关卡id
	blockInfo := &m.LockBlocks{Uid: u.Uid, LockBlocks: make(map[int64]*m.LockBlockSimple, 0)}
	blockInfo.UpdateLockBlock(lockBlockInfo)

	// 更新玩家的第一关卡信息
	lockBlockInfo.Update(lockBlockInfo)
	// u.AddLockBlock(lockBlockInfo)
	u.Update(u)

	// blockInfo.Save()
	// lockBlockInfo.Save()

	// 创建英雄
	CreateHero(u)

	// 创建成就信息
	CreateAchievement(u)
	return
}

func CreateName(name string, count int64) (r string) {
	if name == "" {
		nextId := count % 1000000
		name = fmt.Sprintf("Guest_%06d", nextId)
	}
	return name
}

func CreateIdentifId(count int64) (r string) {
	count += 10000
	left := count / 100000000
	right := count % 100000000

	if left > 0 {
		left = count / 10000000
		upper := Upper[left-10]
		r = fmt.Sprintf("%s%07d", upper, right)
	} else {
		r = fmt.Sprintf("%d", right)
	}
	return
}

func Login(uid string) (u *m.User, err error) {
	if uid == "" {
		err = errors.NewErrcode(data.Errcode.UserNotFound, fmt.Sprintf("无效的uid:%s", uid))
		return
	}
	v, ok := m.Cache.Get("user", uid)
	if !ok {
		err = errors.NewErrcode(data.Errcode.UserNotFound, fmt.Sprintf("玩家未找到 uid:%s", uid))
		return
	}
	u = v.(*m.User)
	return
}

func OnStarChange() *sp.AchievementNoticeRequest {
	return &sp.AchievementNoticeRequest{}
}

// 给物品
// from 来源
// u 用户信息
// kv 具体物品结构
func GiveGoodsByKv(from string, u *m.User, kv m.BaseKV, PSend func(interface{}) error) (uProp *m.UpdateProp, resGoods []*m.Goods, boxResList []*m.BoxRes, err error) {
	resGoods0 := &m.Goods{Num: kv.Val, Tid: kv.Key}
	uProp = m.NewUpdateProp()
	from1 := from
	from = strings.Replace(from, "_multi_true", "", -1)
	defer func() {
		uProp.MergeKvs_Except(
			data.GlobalEnum.NowTime,
			data.GlobalEnum.EnergyTime,
			data.GlobalEnum.NextRecoverTime,
			data.GlobalEnum.Gold,
			data.GlobalEnum.Diamond,
			data.GlobalEnum.Energy,
			data.GlobalEnum.Shield,
		)
		if !strings.HasSuffix(from1, "_multi_true") && err == nil {
			// 更新玩家数据
			u.Update(u)
		}
	}()
	switch kv.Key {
	case 0:
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("无效的物品配置,id:%d", kv.Key))
		return
	case data.GlobalEnum.Gold:
		if from == "UseGridGoods" {
			kv.Val = kv.Val + int64(float64(kv.Val)*float64(u.HandleGoldRate)/float64(100))
			// // 判断额外增加的金币--占卜Buff--Fortune幸运：时间内挖宝金币增加
			// tempScryBuff, tempFindBuff := u.GetScryerInfoData().ScryBuffGet(data.ScryBuffEnum.Fortune)
			// if (tempFindBuff == true) && (tempScryBuff != nil) { // 拿到Buff
			// 	var buffVal float64 = tempScryBuff.Val    // 获取作用值
			// 	kv.Val = int64(float64(kv.Val) * buffVal) // 乘以作用值
			// }
		}
		if from == "SlotReward" {
			rateVal := u.GetUserPet().GetSkillVal(uint64(data.PetSkillEffectEnum.AddSlotGold))
			if rateVal > 0 {
				kv.Val = kv.Val + int64(float64(kv.Val)*float64(rateVal)/float64(100))
			}
		}
		oldGold := u.Gold
		uProp.Kvs = append(uProp.Kvs, u.AddGold(from, kv.Val))
		if kv.Val > 0 {
			// 成就，记录玩家获取的金币
			AddAchievProgress(u, data.AchievementType.Get_gold, kv.Val)
		}
		// 成就，记录玩家拥有最大金币数
		AddAchievProgress(u, data.AchievementType.Hoard_gold, u.Gold)
		// 日志，记录用户获取的金币
		plog.Log_Gold(u, from, oldGold, u.Gold, kv.Val)

		resGoods0.Tid = goldGoods.Tid
		resGoods0.Num = kv.Val
	case data.GlobalEnum.Diamond:
		// 成就，记录获取的宝石数量
		AddAchievProgress(u, data.AchievementType.Get_Gems, kv.Val)

		oldDiamon := u.Diamon
		uProp.Kvs = append(uProp.Kvs, u.AddDiamond(from, kv.Val))
		// 日志，记录玩家钻石获取
		plog.Log_Diamon(u, from, oldDiamon, u.Diamon, kv.Val)
		resGoods0.Tid = diamonGoods.Tid
	case data.GlobalEnum.Energy:
		oldEnergy := u.Energy
		uProp.Kvs = append(uProp.Kvs, u.AddEnergy(from, kv.Val)...)
		// 日志，记录体力获取
		plog.Log_Energy(u, from, oldEnergy, u.Energy, kv.Val)
		resGoods0.Tid = energyGoods.Tid
	case data.GlobalEnum.Shield:
		// 成就，添加获取盾牌数
		AddAchievProgress(u, data.AchievementType.Get_sheild, kv.Val)

		rkvs := u.AddShield(from, kv.Val)
		uProp.Kvs = append(uProp.Kvs, rkvs...)
		for _, rkvsItem := range rkvs {
			if rkvsItem.Key == data.GlobalEnum.Shield {
				resGoods0.Tid = shieldGoods.Tid
				break
			}
			if rkvsItem.Key == data.GlobalEnum.Energy {
				resGoods0.Tid = energyGoods.Tid
				resGoods0.Num = rkvsItem.Val
				break
			}
		}

	case data.GlobalEnum.SlotLv:
		uProp.Kvs = append(uProp.Kvs, u.AddSlotLv(kv.Val))
	case data.GlobalEnum.Star:
		uProp.Kvs = append(uProp.Kvs, u.AddStar(kv.Val))

		// 成就，记录获取星星数量。
		AddAchievProgress(u, data.AchievementType.Get_stars, u.StarVal())
		// 计算新兵特训
		RecruitTrainMsg(u.Uid.Hex(), 0, u.StarSum, 0, PSend)
	case data.GlobalEnum.StarAchiev:
		uProp.Kvs = append(uProp.Kvs, u.AddStarAchiev(kv.Val))
	case data.GlobalEnum.Union:
		if u.UnionId == "" {
			err = errors.NewErrcode(data.Errcode.NoUnion, "没有加入公会")
			return nil, nil, nil, err
		}
		uProp.Kvs = append(uProp.Kvs, u.AddUnionScore(kv.Val))
		resGoods0.Tid = unionScoreGoods.Tid
	default:
		goodsTpl, ok := data.Get("Goods", uint64(kv.Key))
		if !ok {
			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到goods配置,id:%d", kv.Key))
			return
		}
		goodsT := goodsTpl.(data.Good)
		switch int64(goodsT.Category) {
		case data.GoodsCategoryEnum.CategoryLv5:
			resGoods0.Tid = int64(goodsT.Id)
			switch int64(goodsT.Type) {
			case data.GlobalEnum.Gold:
				if from == "UseGridGoods" {
					kv.Val = kv.Val + int64(float64(kv.Val)*float64(u.HandleGoldRate)/float64(100))
					// 判断额外增加的金币--占卜Buff--Fortune幸运：时间内挖宝金币增加
					tempScryBuff, tempFindBuff := u.GetScryerInfoData().ScryBuffGet(data.ScryBuffEnum.Fortune)
					if (tempFindBuff == true) && (tempScryBuff != nil) { // 拿到Buff
						var buffVal float64 = tempScryBuff.Val    // 获取作用值
						kv.Val = int64(float64(kv.Val) * buffVal) // 乘以作用值
					}
				}
				if from == "SlotReward" {
					rateVal := u.GetUserPet().GetSkillVal(uint64(data.PetSkillEffectEnum.AddSlotGold))
					if rateVal > 0 {
						kv.Val = kv.Val + int64(float64(kv.Val)*float64(rateVal)/float64(100))
					}
				}
				resGoods0.Num = kv.Val

				oldGold := u.Gold
				uProp.Kvs = append(uProp.Kvs, u.AddGold(from, kv.Val))
				if kv.Val > 0 {
					// 成就，记录玩家获取的金币
					AddAchievProgress(u, data.AchievementType.Get_gold, kv.Val)
				}
				// 成就，记录玩家拥有最大金币数
				AddAchievProgress(u, data.AchievementType.Hoard_gold, u.Gold)

				// 日志，记录用户获取的金币
				plog.Log_Gold(u, from, oldGold, u.Gold, kv.Val)
			case data.GlobalEnum.Diamond:
				// 成就，记录获取的宝石数量
				AddAchievProgress(u, data.AchievementType.Get_Gems, kv.Val)

				oldDiamon := u.Diamon
				uProp.Kvs = append(uProp.Kvs, u.AddDiamond(from, kv.Val))
				// 日志，记录玩家获取的钻石
				plog.Log_Diamon(u, from, oldDiamon, u.Diamon, kv.Val)
			case data.GlobalEnum.Energy:
				oldEnergy := u.Energy
				uProp.Kvs = append(uProp.Kvs, u.AddEnergy(from, kv.Val)...)
				// 日志，记录玩家获取体力
				plog.Log_Energy(u, from, oldEnergy, u.Energy, kv.Val)
			case data.GlobalEnum.Shield:
				// 成就，添加获取盾牌数
				AddAchievProgress(u, data.AchievementType.Get_sheild, kv.Val)

				rkvs := u.AddShield(from, kv.Val)
				uProp.Kvs = append(uProp.Kvs, rkvs...)
				for _, rkvsItem := range rkvs {
					if rkvsItem.Key == data.GlobalEnum.Shield {
						resGoods0.Tid = shieldGoods.Tid
						break
					}
					if rkvsItem.Key == data.GlobalEnum.Energy {
						resGoods0.Tid = energyGoods.Tid
						resGoods0.Num = rkvsItem.Val
						break
					}
				}
			case data.GlobalEnum.SlotLv:
				uProp.Kvs = append(uProp.Kvs, u.AddSlotLv(kv.Val))
			case data.GlobalEnum.Star:
				uProp.Kvs = append(uProp.Kvs, u.AddStar(kv.Val))

				// 成就，记录获取星星数量。
				AddAchievProgress(u, data.AchievementType.Get_stars, u.StarVal())
				// 计算新兵特训
				RecruitTrainMsg(u.Uid.Hex(), 0, u.StarSum, 0, PSend)
			case data.GlobalEnum.Union:
				if u.UnionId == "" {
					err = errors.NewErrcode(data.Errcode.NoUnion, "没有加入公会")
					return nil, nil, nil, err
				}
				uProp.Kvs = append(uProp.Kvs, u.AddUnionScore(kv.Val))
			default:
				fmt.Println("error goodsT.id", goodsT.Id, "  goodsT.Type : ", goodsT.Type)
			}

		case data.GoodsCategoryEnum.CategoryLv4:
			switch int64(goodsT.Type) {
			case data.GoodsTypeEnum.Props:
				uProp1, err := AddHeroGoods(u, goodsT, kv.Val, PSend)
				if err != nil {
					return nil, nil, nil, err
				}
				// 成就，获取卡牌数
				AddAchievProgress(u, data.AchievementType.Collect_cards, kv.Val)
				uProp.Merge(uProp1)
			}
			// 物品是宝箱， 帮它使用
		case data.GoodsCategoryEnum.CategoryLv3:
			if int64(goodsT.Type) == data.GoodsTypeEnum.Specialchest { // 5选1宝箱
				resGoods0.Tid = int64(goodsT.Id)
				resGoods0.Num = 1
				err := GiveSpBoxToUser(u)
				if err != nil {
					return nil, nil, nil, err
				}
			} else {
				uProp1, _, boxResList0, err := UseGood(from, u, goodsT, PSend)
				if err != nil {
					return nil, nil, nil, err
				}
				uProp.Merge(uProp1)
				boxResList = append(boxResList, boxResList0...)
			}
		case data.GoodsCategoryEnum.CategoryLv8:
			switch int64(goodsT.Type) {
			case data.GoodsTypeEnum.Pet: // 给宠物
				kv, pet, upropPetInfo, err := AddPet(u, utils.Int64(goodsT.Effect))
				if err != nil {
					return nil, nil, nil, err
				}
				if upropPetInfo != nil {
					uProp.Petinfo = upropPetInfo
				}
				if pet != nil {
					uProp.Pets = append(uProp.Pets, pet)
				}
				if kv != nil {
					uProp.Kvs = append(uProp.Kvs, kv)
				}
			case data.GoodsTypeEnum.PetFood: // 给宠物食物
				uProp.Petinfo = u.GetUserPet().AddFoodNum(kv.Val)
			case data.GoodsTypeEnum.PetExp: // 给宠物经验
				uProp.Petinfo = u.GetUserPet().AddExpNum(kv.Val)
			}
		case data.GoodsCategoryEnum.CategoryLv10:
			switch int64(goodsT.Type) {
			case data.GoodsTypeEnum.PictureFrame: //给头像框
				needCallClient, _, _ := u.AddAvatarFrame(int64(goodsT.Id))
				if needCallClient {
					resGoods0.Tid = int64(goodsT.Id)
					resGoods0.Num = 1
				}
				AvatarFrameMsg(u, PSend)
			}
		case data.GoodsCategoryEnum.CategoryLv11: // 大奖
			oldGold := u.Gold
			uProp.Kvs = append(uProp.Kvs, u.AddGold(from, kv.Val))
			if kv.Val > 0 { // 成就，记录玩家获取的金币
				AddAchievProgress(u, data.AchievementType.Get_gold, kv.Val)
			}
			AddAchievProgress(u, data.AchievementType.Hoard_gold, u.Gold) // 成就，记录玩家拥有最大金币数

			plog.Log_Gold(u, from, oldGold, u.Gold, kv.Val) // 日志，记录用户获取的金币
		default:
			fmt.Println("GiveGoodsByKv : ", kv)
		}
	}
	resGoods = append(resGoods, resGoods0)
	return
}

// 批量给物品
func GiveGoodsByKvList(from string, u *m.User, list []m.BaseKV, PSend func(interface{}) error) (uProp *m.UpdateProp, resGoodsList []*m.Goods, boxResList []*m.BoxRes, err error) {
	uProp = m.NewUpdateProp()
	defer uProp.MergeKvs_Except(
		data.GlobalEnum.NowTime,
		data.GlobalEnum.EnergyTime,
		data.GlobalEnum.NextRecoverTime,
		data.GlobalEnum.Gold,
		data.GlobalEnum.Diamond,
		data.GlobalEnum.Energy,
		data.GlobalEnum.Shield,
	)
	u1 := *u // 先对u 进行浅拷贝
	for _, item := range list {
		uProp1, resGoods, boxResList0, err := GiveGoodsByKv(from, &u1, item, PSend)
		if err != nil {
			return nil, nil, nil, err
		}

		resGoodsList = append(resGoodsList, resGoods...)
		boxResList = append(boxResList, boxResList0...)
		uProp.Merge(uProp1)
	}
	u.ShallowSet(u1)
	return
}

func CheckCost(u *m.User, list []m.BaseKV) error {
	u1 := *u
	_, err := Cost("CheckCost", &u1, list)
	return err
}

// 扣物品
func Cost(from string, u *m.User, list []m.BaseKV) (uProp *m.UpdateProp, err error) {
	uProp = &m.UpdateProp{Kvs: make([]*m.BaseKV, 0)}
	u1 := *u
	for _, kv := range list {
		rkvs, err := cost(from, &u1, kv)
		if err != nil {
			return nil, err
		}
		uProp.Kvs = append(uProp.Kvs, rkvs...)
	}
	uProp.MergeKvs_Except(
		data.GlobalEnum.NowTime,
		data.GlobalEnum.EnergyTime,
		data.GlobalEnum.NextRecoverTime,
		data.GlobalEnum.Gold,
		data.GlobalEnum.Diamond,
		data.GlobalEnum.Energy,
		data.GlobalEnum.Shield,
	)
	u.ShallowSet(u1)
	return
}

func cost(from string, u *m.User, kv m.BaseKV) (rkvs []*m.BaseKV, err error) {
	val := kv.Val
RB:
	switch kv.Key {
	case data.GlobalEnum.Gold:
		if u.Gold < val {
			err = errors.NewErrcode(data.Errcode.NoGold, "钱不够")
			return
		}
		oldGold := u.Gold
		rkvs = append(rkvs, u.AddGold(from, -val))
		plog.Log_Gold(u, from, oldGold, u.Gold, -val) //记录消耗金币
	case data.GlobalEnum.Diamond:
		if u.Diamon < val {
			err = errors.NewErrcode(data.Errcode.NoDiamond, "砖石不够")
			return
		}
		rkvs = append(rkvs, u.AddDiamond(from, -val))
	case data.GlobalEnum.Energy:
		if u.Energy < val {
			err = errors.NewErrcode(data.Errcode.NoEnergy, "体力不够")
			return
		}

		rkvs = append(rkvs, u.AddEnergy(from, -val)...)

		// 成就，消耗体力，重置连续打开的格子数
		AchievAuxiliResetCOG(u)
		// 成就，一天内消耗的体力
		AchievAuxiliOD(u, -val)
	case data.GlobalEnum.Shield:
		if u.Shield < val {
			err = errors.NewErrcode(data.Errcode.NoShield, "没有盾牌")
			return
		}
		rkvs = append(rkvs, u.AddShield(from, -val)...)
	case data.GlobalEnum.Union:
		if u.UnionId == "" {
			err = errors.NewErrcode(data.Errcode.NoUnion, "没有加入公会")
			return
		}
		if u.UnionScore < val {
			err = errors.NewErrcode(data.Errcode.NoUnionScore, "公会积分不足")
			return
		}
		rkvs = append(rkvs, u.AddUnionScore(-val))
	default:
		goodsTpl, ok := data.Get("Goods", uint64(kv.Key))
		if !ok {
			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到goods配置,id:%d", kv.Key))
			return
		}
		goodsT := goodsTpl.(data.Good)
		if int64(goodsT.Category) == data.GoodsCategoryEnum.CategoryLv5 {
			kv.Key = int64(goodsT.Type)
			goto RB
		}
		fmt.Println("cost kv:", kv)
	}
	return
}

// 登录验证
func AuthLogin(accountId string, token string, platform int64) (r bool, err error) {
	var mdata map[string]string = map[string]string{
		"accountId": accountId,
		"token":     token,
	}
	b, err := json.Marshal(mdata)
	if err != nil {
		return
	}
	body := bytes.NewReader(b)
	// 华为-聚合SDK
	if 6 == platform {
		return true, nil
	}
	// 非聚合SDK
	res, err := http.Post(conf.Conf.AuthLoginAddress, "application/json", body)
	if err != nil {
		return
	}
	defer res.Body.Close()

	resB, _ := ioutil.ReadAll(res.Body)

	var resdata struct {
		Msg        string `json:"msg"`
		StatusCode int64  `json:"statusCode"`
	}
	err = json.Unmarshal(resB, &resdata)
	if err != nil {
		return
	}
	if resdata.StatusCode != 1 {
		err = errors.New(fmt.Sprintf("验证失败, msg: %s  statusCode:%d", resdata.Msg, resdata.StatusCode))
		return
	}
	r = true
	return
}

// 获取UID玩家当前的金币数
func GetUserGold(uidString string) (gold int64, err error) {
	u := new(m.User)
	Uid := bson.ObjectIdHex(uidString)                                      // 参考game/m/user.go Load
	err = dbmodule.MgoDB.GameDB.FindOne("user", bson.M{"_id": Uid}, nil, u) // 参考game/m/user.go LoadData
	if err != nil {
		if err.Error() == "not found" {
			err = errors.NewErrcode(data.Errcode.UserNotFound, "角色不存在")
			return 0, err
		}
		return 0, err
	}
	gold = u.Gold
	return gold, nil
}

// 查找
func FindUidByAccountId(accountId string) (uid string, err error) {
	u := new(m.User)
	err = dbmodule.MgoDB.GameDB.FindOne("user", bson.M{"accountId": accountId}, bson.M{"_id": 1, "accountId": 1}, u)
	if err != nil {
		err = errors.NewErrcode(data.Errcode.UserNotFound, err.Error())
		return
	}
	uid = u.Uid.Hex()
	return
}

// 查找
func FindUidByIdentifId(identifId string) (uid string, err error) {
	u := new(m.User)
	err = dbmodule.MgoDB.GameDB.FindOne("user", bson.M{"identifId": identifId}, bson.M{"_id": 1, "identifId": 1}, u)
	if err != nil {
		err = errors.NewErrcode(data.Errcode.UserNotFound, err.Error())
		return
	}
	uid = u.Uid.Hex()
	return
}

// 通过用户名查询用户信息
func FindUserListByName(name string) (r []*m.User, err error) {
	r = make([]*m.User, 0)
	err = dbmodule.MgoDB.GameDB.FindAll("user", bson.M{"name": name}, nil, &r)
	return
}

// 通过用户名查询用户信息
func FindUserListBySuperAccount(superAccount int64) (r []*m.User, err error) {
	r = make([]*m.User, 0)
	err = dbmodule.MgoDB.GameDB.FindAll("user", bson.M{"superAccount": superAccount}, nil, &r)
	return
}

// 统计在线玩家
func CountOnline() (r int, err error) {
	r, err = dbmodule.MgoDB.GameDB.Count("user", bson.M{"offline_time": 0})
	return
}

// 统计玩家数量
func CountUser() (r int, err error) {
	r, err = dbmodule.MgoDB.GameDB.Count("user", nil)
	return
}

// 分页查询 在线玩家
func FindOnLinePage(page, pageNum int) (r []*m.User, err error) {
	r = make([]*m.User, 0)
	err = dbmodule.MgoDB.GameDB.FindPageSort("user", page, pageNum, bson.M{"offline_time": 0}, nil, []string{"-last_login_time"}, &r)
	return
}

// 分页查询离线玩家
func FindOffLinePage(start, pageNum int) (r []*m.User, err error) {
	r = make([]*m.User, 0)
	err = dbmodule.MgoDB.GameDB.FindPageSort2("user", start, pageNum, bson.M{"offline_time": bson.M{"$gt": 0}}, nil, []string{"-offline_time"}, &r)
	return
}

func FindUidByName(name string) (uid []string, err error) {
	userGroup := make([]*m.User, 0)
	err = dbmodule.MgoDB.GameDB.FindAllSortLimit("user", bson.M{"name": name}, nil, &userGroup, []string{"-_uid"}, 10)
	if err != nil {
		err = errors.NewErrcode(data.Errcode.UserNotFound, err.Error())
		return
	}
	for _, item := range userGroup {
		uid = append(uid, item.Uid.Hex())
	}
	return
}

func FindUserByGroup(groupId int64) (userGroup []*m.User, err error) {
	userGroup = make([]*m.User, 0)
	err = dbmodule.MgoDB.GameDB.FindAllSortLimit("user", bson.M{"userGroup": groupId}, nil, &userGroup, []string{"-_uid"}, 10)
	if err != nil {
		err = errors.NewErrcode(data.Errcode.UserNotFound, err.Error())
		return nil, err
	}
	return userGroup, nil
}

func LanguageChange(u *m.User, langsTyp string) (err error) {
	u.LangsTyp = langsTyp
	u.Update(u)
	return
}

func GetUser(uid string) (r *m.User) {
	r = m.GetUser(uid)
	return
}

// 发送头像框
func AvatarFrameMsg(u *m.User, PSend func(interface{}) error) {
	if PSend == nil {
		return
	}
	PSend(&sp.AvatarFrameUpdateRequest{
		AvatarFrame:    u.AvatarFrame,
		AvatarFrameArr: FormatAvatarFramesArr(u.AvatarFrameArr),
	})
}

func GetLanguage(id string, langsTyp string) (r string, err error) {
	tpl, ok := data.Get("CodeTextLangs", id)
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有该CodeTextLangs配表，或没有该数据 %s", id))
		return
	}
	tplT := tpl.(data.Language)

	switch langsTyp {
	case "zh":
		r = tplT.Zh
	case "tc":
		r = tplT.Tracn
	case "en":
		r = tplT.En
	case "pt":
		r = tplT.Por
	case "jp":
		r = tplT.Jp
	case "korea":
		r = tplT.Korea
	case "fr":
		r = tplT.France
	case "es":
		r = tplT.Spanish
	case "ro":
		r = tplT.Rom
	case "de":
		r = tplT.Ger
	case "it":
		r = tplT.Ita
	default:
		r = tplT.En
	}
	return
}
